package com.letv.mq.addMms;

import java.sql.Connection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.PropertyConfigurator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSON;
import com.letv.common.ConnectionManager;
import com.letv.common.Mappings;
import com.letv.common.ProcessData;
import com.letv.dataprocess.DataprocessServiceImpl;
import com.letv.mq.MqPipLineAddMssAlbum;
import com.letv.mq.addMms.MqAddBean.Type;
import com.letv.util.CommonUtil;
import com.letv.util.SQLUtil;
import com.panguso.ps.common.conf.ConfigFactory;

/**
 * 为解决从库同步问题，处理增量媒资消息的静态工具类
 */
public class DataHandle {

    /**
     * Logger
     */
    private final static Logger LOGGER = LoggerFactory.getLogger(DataHandle.class);

    /**
     * String, 离线计算中的媒资专辑标志
     */
    private static final String MARK_ALBUM_TYPE = "album";

    /**
     * String, 离线计算中的媒资视频标志
     */
    private static final String MARK_VIDEO_TYPE = "video";

    public static void dataHandle(String data) {
        Connection connectionOffline = null;
        try {
            LOGGER.info("mq mms pipline,receive data=" + data);
            ConnectionManager connectionManager = ConnectionManager.getInstance();
            connectionOffline = connectionManager.getConnection();
            MqAddBean mqAddBean = DataHandle.calculateMqAddBean(data, connectionOffline);
            if(null == mqAddBean) {
                return;
            }
            LOGGER.info("mq mms pipline,begin to insert,type=" + mqAddBean.getType().toString() + ",id=" + mqAddBean.getId());
            DataHandle.mqOffLineInsert(mqAddBean, connectionManager, connectionOffline);
        } catch(Exception e) {
            LOGGER.error("method DataHandle.dataHandle catch error", e);
        } finally {
            SQLUtil.close(connectionOffline);
        }
    }

    /**
     * 将传入消息插入到离线计算表及缓存中
     * @param mqAddBean MqAddBean
     * @param connectionManager ConnectionManager
     * @param connectionOffline Connection, 离线计算数据库连接
    * @throws Exception
     */
    private static void mqOffLineInsert(MqAddBean mqAddBean, ConnectionManager connectionManager, Connection connectionOffline) throws Exception {
        if(!DataHandle.checkMqInsert(connectionManager, connectionOffline)) {
            return;
        }

        // mq --> down
        String sqlString = null;
        if(Type.ALBUM.equals(mqAddBean.getType())) {
            sqlString = ProcessData.getAlbumStr(DataHandle.calculateMap(mqAddBean.getMqAlbumBean()));
            SQLUtil.insertSingleSourceData(connectionOffline, DataHandle.MARK_ALBUM_TYPE, sqlString);
        } else {
            sqlString = ProcessData.getVideoStr(DataHandle.calculateMap(mqAddBean.getMqVideoBean()));
            SQLUtil.insertSingleSourceData(connectionOffline, DataHandle.MARK_VIDEO_TYPE, sqlString);
        }

        // down --> process
        if(Type.ALBUM.equals(mqAddBean.getType())) {
            new DataprocessServiceImpl().processDataById(DataHandle.MARK_ALBUM_TYPE, mqAddBean.getId());
        } else {
            new DataprocessServiceImpl().processDataById(DataHandle.MARK_VIDEO_TYPE, mqAddBean.getId());
        }
    }

    /**
     * 检查mq插入离线计算准备工作是否做好，若未做好则做好
     * @param connectionManager ConnectionManager
     * @param connectionOffline Connection, 离线计算数据库连接
     * @return true--准备工作完成,false--准备工作出错
     */
    private static boolean checkMqInsert(ConnectionManager connectionManager, Connection connectionOffline) {
        if(null != Mappings.DICTIONARY_MAP && Mappings.DICTIONARY_MAP.size() > 0) {
            return true;
        }
        Connection connectionLeso = null;
        Connection connectionMms = null;
        try {
            connectionMms = connectionManager.getConnectionFromMMS();
            connectionLeso = connectionManager.getConnectionFromLeso();
            SQLUtil.setDictionary(connectionMms);
            SQLUtil.setStar(connectionMms);
            SQLUtil.setRAlbumMap(connectionMms);
            SQLUtil.setCagegoryMapping(connectionLeso);
            return true;
        } catch(Exception e) {
            return false;
        } finally {
            SQLUtil.close(connectionLeso);
            SQLUtil.close(connectionMms);
        }
    }

    /**
     * 计算媒资专辑map
     * @param mqAlbumBean MqAlbumBean
     * @return Map<String, Object>
     */
    private static Map<String, Object> calculateMap(MqAlbumBean mqAlbumBean) {
        Map<String, Object> result = new HashMap<String, Object>();
        result.put("ID", mqAlbumBean.getId());
        result.put("ALBUM_TYPE", DataHandle.getMapUniqueKey(mqAlbumBean.getAlbumType()));
        result.put("SOURCE_ID", DataHandle.getMapUniqueKey(mqAlbumBean.getSourceId()));
        result.put("NAME_CN", mqAlbumBean.getNameCn());
        result.put("NAME_EN", mqAlbumBean.getNameEn());
        result.put("SUB_TITLE", mqAlbumBean.getSubTitle());
        result.put("ALIAS", mqAlbumBean.getAlias());
        result.put("SHORT_DESC", mqAlbumBean.getShortDesc());
        result.put("DESCRIPTION", mqAlbumBean.getDescription());
        result.put("TAG", mqAlbumBean.getTag());
        result.put("SCORE", mqAlbumBean.getScore()); 
        result.put("CATEGORY", DataHandle.getMapUniqueKey(mqAlbumBean.getCategory())); 
        result.put("SUB_CATEGORY", DataHandle.getMapJoinKey(mqAlbumBean.getSubCategory())); 
        result.put("DOWNLOAD_PLATFORM", DataHandle.getMapJoinKey(mqAlbumBean.getDownloadPlatform())); 
        result.put("PLAY_PLATFORM", DataHandle.getMapJoinKey(mqAlbumBean.getPlayPlatform())); 
        result.put("PAY_PLATFORM", DataHandle.getMapJoinKey(mqAlbumBean.getPayPlatform())); 
        result.put("STATUS", mqAlbumBean.getStatus());
        result.put("DELETED", mqAlbumBean.getDeleted());
        result.put("IS_END", mqAlbumBean.getIsEnd());
        result.put("IS_HEIGHT", mqAlbumBean.getIsHeight());
        result.put("AREA", DataHandle.getMapJoinKey(mqAlbumBean.getArea())); 
        result.put("COPYRIGHT_TYPE", DataHandle.getMapUniqueKey(mqAlbumBean.getCopyrightType())); 
        result.put("DURATION", mqAlbumBean.getDuration());
        result.put("RELEASE_DATE", mqAlbumBean.getReleaseDate());
        result.put("DOUBAN_ID", mqAlbumBean.getDoubanId());
        result.put("EPISODE", mqAlbumBean.getEpisode());
        result.put("PLAY_STATUS", mqAlbumBean.getPlayStatus());
        result.put("MAKER_COMPANY", mqAlbumBean.getMakerCompany());
        result.put("DIRECTORY", DataHandle.getMapListJoinKey(mqAlbumBean.getDirectory()));
        result.put("ACTOR", DataHandle.getMapListJoinKey(mqAlbumBean.getActor()));
        result.put("STARRING", DataHandle.getMapListJoinKey(mqAlbumBean.getStarring()));
        result.put("STARRING_PLAY", mqAlbumBean.getStarringPlay());
        result.put("PIC_COLLECTIONS", DataHandle.removeJsonTransfer(mqAlbumBean.getPicCollections()));
        result.put("SCREEN_WRITER", mqAlbumBean.getScreenWriter());
        result.put("MAKER", mqAlbumBean.getMaker());
        result.put("FILM_BASE_TYPE", DataHandle.getMapUniqueKey(mqAlbumBean.getFilmBaseType())); 
        result.put("R_COMPANY", mqAlbumBean.getrCompany());
        result.put("LANGUAGE", DataHandle.getMapUniqueKey(mqAlbumBean.getLanguage())); 
        result.put("FIT_AGE", DataHandle.getMapJoinKey(mqAlbumBean.getFitAge())); 
        result.put("CAST", DataHandle.getMapListJoinKey(mqAlbumBean.getCast()));
        result.put("COMPERE", DataHandle.getMapListJoinKey(mqAlbumBean.getCompere()));
        result.put("SUPERVISE", DataHandle.getMapListJoinKey(mqAlbumBean.getSupervise()));
        result.put("ORIGINATOR", DataHandle.getMapListJoinKey(mqAlbumBean.getOriginator()));
        result.put("IS_PAY", mqAlbumBean.getIsPay());
        result.put("RELATION_ID", mqAlbumBean.getRelationId());
        result.put("IS_HOMEMADE", mqAlbumBean.getIsHomemade());
        result.put("PLAY_CONTROL_PLATFORM_CNTV", mqAlbumBean.getPlayControlPlatformCntv());
        result.put("PLAY_CONTROL_PLATFORM_HUASHU", mqAlbumBean.getPlayControlPlatformHuashu());
        result.put("PLAY_CONTROL_PLATFORM_GUOGUANG", mqAlbumBean.getPlayControlPlatformGuoguang());
        result.put("CREATE_TIME", mqAlbumBean.getCreateTime());
        result.put("UPDATE_TIME", mqAlbumBean.getUpdateTime());
        result.put("VARIETY_SHOW", mqAlbumBean.getVarietyShow());
        result.put("APPID", DataHandle.getMapJoinKey(mqAlbumBean.getAppid()));
        result.put("VIDS", DataHandle.getVideoIds(mqAlbumBean.getVideoList()));
        result.put("VID_EPISODE", DataHandle.getVidEpisode(mqAlbumBean.getVideoList()));
        result.put("ZH_DIRECTORY", DataHandle.getMapListJoinValue(mqAlbumBean.getDirectory()));
        result.put("ZH_STARRING", DataHandle.getMapListJoinValue(mqAlbumBean.getStarring()));
        result.put("STYLE", DataHandle.getMapJoinKey(mqAlbumBean.getStyle()));
        result.put("CONTENT_RATING", DataHandle.getMapUniqueKey(mqAlbumBean.getContentRating()));
        result.put("ALBUM_PIC", mqAlbumBean.getAlbumPic());
        return result;
    }

    /**
     * 计算媒资视频map
     * @param mqVideoBean MqVideoBean
     * @return Map<String, Object>
     */
    private static Map<String, Object> calculateMap(MqVideoBean mqVideoBean) {
        Map<String, Object> result = new HashMap<String, Object>();
        result.put("ID", mqVideoBean.getId());
        result.put("SOURCE_ID", DataHandle.getMapUniqueKey(mqVideoBean.getSourceId()));
        result.put("VIDEO_TYPE", DataHandle.getMapUniqueKey(mqVideoBean.getVideoType()));
        result.put("PID", mqVideoBean.getPid());
        result.put("PORDER", mqVideoBean.getPorder());
        result.put("MID", mqVideoBean.getMid());
        result.put("NAME_CN", mqVideoBean.getNameCn());
        result.put("NAME_EN", mqVideoBean.getNameEn());
        result.put("ALIAS", mqVideoBean.getAlias());
        result.put("SUB_TITLE", mqVideoBean.getSub_title());
        result.put("SHORT_DESC", mqVideoBean.getShort_desc());
        result.put("DESCRIPTION", mqVideoBean.getDescription());
        result.put("TAG", mqVideoBean.getTag());
        result.put("CATEGORY", DataHandle.getMapUniqueKey(mqVideoBean.getCategory()));
        result.put("SUB_CATEGORY", DataHandle.getMapJoinKey(mqVideoBean.getSubCategory())); 
        result.put("EPISODE", mqVideoBean.getEpisode());
        result.put("WATCHING_FOCUS", mqVideoBean.getWatchingFocus());
        result.put("COPYRIGHT_TYPE", DataHandle.getMapUniqueKey(mqVideoBean.getCopyrightType()));
        result.put("COPYRIGHT_COMPANY", mqVideoBean.getCopyrightCompany());
        result.put("DOWNLOAD_PLATFORM", DataHandle.getMapJoinKey(mqVideoBean.getDownloadPlatform()));
        result.put("PLAY_PLATFORM", DataHandle.getMapJoinKey(mqVideoBean.getPlayPlatform()));
        result.put("PAY_PLATFORM", DataHandle.getMapJoinKey(mqVideoBean.getPayPlatform()));
        result.put("DURATION", mqVideoBean.getDuration());
        result.put("STATUS", mqVideoBean.getStatus());
        result.put("DELETED", mqVideoBean.getDeleted());
        result.put("SCORE", mqVideoBean.getScore());
        result.put("RELATIVE_CONTENT", mqVideoBean.getRelativeContent());
        result.put("RELEASE_DATE", mqVideoBean.getReleaseDate());
        result.put("AREA", DataHandle.getMapJoinKey(mqVideoBean.getArea()));
        result.put("IS_HOMEMADE", mqVideoBean.getIsHomemade());
        result.put("STARRING", DataHandle.getMapListJoinKey(mqVideoBean.getStarring()));
        result.put("DIRECTORY", DataHandle.getMapListJoinKey(mqVideoBean.getDirectory()));
        result.put("ACTOR", DataHandle.getMapListJoinKey(mqVideoBean.getActor()));
        result.put("LANGUAGE", DataHandle.getMapUniqueKey(mqVideoBean.getLanguage()));
        result.put("GUEST", DataHandle.getMapListJoinKey(mqVideoBean.getGuest()));
        result.put("SINGER_TYPE", DataHandle.getMapUniqueKey(mqVideoBean.getSingerType()));
        result.put("MUSIC_AUTHORS", mqVideoBean.getMusicAuthors());
        result.put("RECORD_COMPANY", mqVideoBean.getRecordCompany());
        result.put("CREATE_TIME", mqVideoBean.getCreateTime());
        result.put("UPDATE_TIME", mqVideoBean.getUpdateTime());
        result.put("ZH_ACTOR", DataHandle.getMapListJoinValue(mqVideoBean.getActor()));
        result.put("ZH_DIRECTORY", DataHandle.getMapListJoinValue(mqVideoBean.getDirectory()));
        result.put("APPID", DataHandle.getMapJoinKey(mqVideoBean.getAppid()));
        result.put("PLAY_CONTROL_PLATFORM_CNTV", mqVideoBean.getPlayControlPlatformCntv());
        result.put("PLAY_CONTROL_PLATFORM_HUASHU", mqVideoBean.getPlayControlPlatformHuashu());
        result.put("PLAY_CONTROL_PLATFORM_GUOGUANG", mqVideoBean.getPlayControlPlatformGuoguang());
        result.put("VIDEO_PIC", mqVideoBean.getVideoPic());
        result.put("PIC_UPLOAD", DataHandle.removeJsonTransfer(mqVideoBean.getPicUpload()));
        result.put("CONTENT_RATING", DataHandle.getMapUniqueKey(mqVideoBean.getContentRating()));
        result.put("AUTO_VIDEO_PIC", mqVideoBean.getAutoVideoPic());
        result.put("IS_PAY", mqVideoBean.getIsPay());
        return result;
    }

    /**
     * 返回List<Map>中的value用拼接符拼接而成的字符串（保持map在list中的顺序）
     * @param map Map<String, String>
     * @return String, 为空或出错则返回null
     */
    private static String getMapListJoinValue(List<Map<String, String>> mapList) {
        if(null == mapList || mapList.size() == 0) {
            return null;
        }
        String result = null;
        try {
            StringBuffer resultBuffer = new StringBuffer("");
            for(int i = 0; i < mapList.size(); i++) {
                if(null == mapList.get(i)) {
                    continue;
                }
                for (String value : mapList.get(i).values()) {
                    if(StringUtils.isBlank(value)) {
                        continue;
                    }
                    resultBuffer.append(value).append(CommonUtil.COMMON_JOIN_CHARACTER);
                }
            }
            if(resultBuffer.length() > 0) {
                result = resultBuffer.deleteCharAt(resultBuffer.length() - 1).toString();
            }
        } catch(Exception e) {
            result = null;
        }
        return result;
    }

    /**
     * 返回专辑下的单视频 id-episode 拼接而成的字符串
     * @param videoList List<MqVideoInAlbumBean>
     * @return String
     */
    private static String getVidEpisode(List<MqVideoInAlbumBean> videoList) {
        if(null == videoList || videoList.size() == 0) {
            return null;
        }
        String result = null;
        try {
            StringBuffer resultBuffer = new StringBuffer("");
            for(int i = 0; i < videoList.size(); i++) {
                if(null == videoList.get(i) || null == videoList.get(i).getId() || null == videoList.get(i).getEpisode()) {
                    continue;
                }
                resultBuffer.append(videoList.get(i).getEpisode()).append("-").append(videoList.get(i).getId().toString()).append(CommonUtil.COMMON_JOIN_CHARACTER);
            }
            if(resultBuffer.length() > 0) {
                result = resultBuffer.deleteCharAt(resultBuffer.length() - 1).toString();
            }
        } catch(Exception e) {
            result = null;
        }
        return result;
    }

    /**
     * 返回专辑下的单视频id拼接而成的字符串
     * @param videoList List<MqVideoInAlbumBean>
     * @return String
     */
    private static String getVideoIds(List<MqVideoInAlbumBean> videoList) {
        if(null == videoList || videoList.size() == 0) {
            return null;
        }
        String result = null;
        try {
            StringBuffer resultBuffer = new StringBuffer("");
            for(int i = 0; i < videoList.size(); i++) {
                if(null == videoList.get(i) || null == videoList.get(i).getId()) {
                    continue;
                }
                resultBuffer.append(videoList.get(i).getId().toString()).append(CommonUtil.COMMON_JOIN_CHARACTER);
            }
            if(resultBuffer.length() > 0) {
                result = resultBuffer.toString();
            }
        } catch(Exception e) {
            result = null;
        }
        return result;
    }

    /**
     * 去掉传入json字符串中的转义字符
     * @param infectantJson String
     * @return String
     */
    private static String removeJsonTransfer(String infectantJson) {
        if(StringUtils.isBlank(infectantJson)) {
            return null;
        }
        String result = null;
        try {
            result = JSON.toJSONString(JSON.parseObject(infectantJson));
        } catch(Exception e) {
            result = null;
        }
        return result;
    }

    /**
     * 返回List<Map>中的key用拼接符拼接而成的字符串（保持map在list中的顺序）
     * @param map Map<String, String>
     * @return String, 为空或出错则返回null
     */
    private static String getMapListJoinKey(List<Map<String, String>> mapList) {
        if(null == mapList || mapList.size() == 0) {
            return null;
        }
        String result = null;
        try {
            StringBuffer resultBuffer = new StringBuffer("");
            for(int i = 0; i < mapList.size(); i++) {
                if(null == mapList.get(i)) {
                    continue;
                }
                for (String key : mapList.get(i).keySet()) {
                    if(StringUtils.isBlank(key)) {
                        continue;
                    }
                    resultBuffer.append(key).append(CommonUtil.COMMON_JOIN_CHARACTER);
                }
            }
            if(resultBuffer.length() > 0) {
                result = CommonUtil.COMMON_JOIN_CHARACTER + resultBuffer.toString();
            }
        } catch(Exception e) {
            result = null;
        }
        return result;
    }

    /**
     * 返回map中的key用拼接符拼接而成的字符串
     * @param map Map<String, String>
     * @return String, 为空或出错则返回null
     */
    private static String getMapJoinKey(Map<String, String> map) {
        if(null == map) {
            return null;
        }
        String result = null;
        try {
            StringBuffer resultBuffer = new StringBuffer("");
            for (String key : map.keySet()) {
                if(StringUtils.isBlank(key)) {
                    continue;
                }
                resultBuffer.append(key).append(CommonUtil.COMMON_JOIN_CHARACTER);
            }
            if(resultBuffer.length() > 0) {
                result = CommonUtil.COMMON_JOIN_CHARACTER + resultBuffer.toString();
            }
        } catch(Exception e) {
            result = null;
        }
        return result;
    }

    /**
     * 认为map中只有一个key，返回该key值
     * @param map Map<String, String>
     * @return Integer, 为空或出错则返回null
     */
    private static Integer getMapUniqueKey(Map<String, String> map) {
        if(null == map) {
            return null;
        }
        Integer result = null;
        try {
            for (String key : map.keySet()) {
                if(StringUtils.isBlank(key)) {
                    continue;
                }
                result = Integer.parseInt(key);
                break;
            }
        } catch(Exception e) {
            result = null;
        }
        return result;
    }

    /**
     * 根据传入字符串计算出对应的消息体结构
     * @param data String
     * @param connectionOffline Connection, 离线计算数据库连接
     * @return MqAddBean, 为空或数据不合法则返回null
     * @throws Exception
     */
    private static MqAddBean calculateMqAddBean(String data, Connection connectionOffline) throws Exception {
        if(StringUtils.isBlank(data)) {
            return null;
        }
        String[] dataArray = data.split("\t");
        if(dataArray.length != 3) {
            return null;
        }
        long id = Long.parseLong(dataArray[0].trim());
        String typeString = dataArray[1].trim();
        String realData = CommonUtil.decompressZlibBase64(dataArray[2].trim());
        if(StringUtils.isBlank(realData)) {
            LOGGER.error("mq mms pipline fail to decode,id=" + id + ",type=" + typeString);
            return null;
        }
        MqAddBean result = null;
        try {
            if(DataHandle.MARK_ALBUM_TYPE.equals(typeString)) {
                result = new MqAddBean(id, Type.ALBUM, JSON.parseObject(realData, MqAlbumBean.class), null);
                if(null != result.getMqAlbumBean().getDeleted() && 1 == result.getMqAlbumBean().getDeleted()) {
                    LOGGER.info("mq mms pipline data is deleted,id=" + id + ",type=" + result.getType().toString());
                    return null;
                }
                
            } else if(DataHandle.MARK_VIDEO_TYPE.equals(typeString)) {
                result = new MqAddBean(id, Type.VIDEO, null, JSON.parseObject(realData, MqVideoBean.class));
                if(null != result.getMqVideoBean().getDeleted() && 1 == result.getMqVideoBean().getDeleted()) {
                    LOGGER.info("mq mms pipline data is deleted,id=" + id + ",type=" + result.getType().toString());
                    return null;
                }
            } else {
                return null;
            }
        } catch(Exception e) {
            LOGGER.error("mq mms pipline fail to mapping,id=" + id + ",type=" + typeString, e);
            return null;
        }
        if(SQLUtil.getMmsCountById(connectionOffline, result.getType(), id) > 0) {
            LOGGER.info("mq mms pipline already have data,id=" + id + ",type=" + result.getType().toString());
            return null;
        }
        return result;
    }

    public static void main(String[] args) {
        ConfigFactory.init("E:\\code\\mms\\search_java\\offline_task\\trunk\\target\\ROOT\\WEB-INF\\classes\\config.xml");
        String log4jPath = "E:\\code\\mms\\search_java\\offline_task\\trunk\\target\\ROOT\\WEB-INF\\classes\\log4j.properties";
        PropertyConfigurator.configure(log4jPath);
        MqPipLineAddMssAlbum.start();
//        StringBuffer sb = new StringBuffer("10034589").append("\t").append("album").append("\t").append("eJztfWuTlEWa9l/p6C/7rkFaeT70N1dm3zViYdx3mN3YWCeIPEIrTRPdjQ4YE4GDICCgzDjoCIqHddUd8fTqCggSMT9lpqu6+bR/Ya98qqv6UF3V1Tbi7C4GNvXk83TdT2beeV/XdeeB5yf9oXB05snpODk1eXBh4chUqzXNHz2UF56dnjnwaJydaR2KVO+fnn92br7FKTOUt6hsMd3isiWND6IoTUQ2nMhiNXEsCBKVZN46Q4PNk7u6JvYdO5Inp56fZJZSymHt3nsvti+dWzr70uSv6iPTfh6Fj03snj3wV/MTTx6dOzI7n1uLN24t3jq9eOPi4p13lq7cuPfCS/+n/crnf12/dC77+n2KUsPwm0vfXWxfuVO/K/rDP8t+Lh6cnGL1aiEfmJ071tiuz732dfvOF93nund+8ssFlD//K3xpnD28kA8v/D+/MH34QP0NzfG2Crfbpz5q3/zq3ncvdj79uvnl2SPH5qYPHFzo1as+KPFg5/V3ls6e6bx1snkKL7mQ903P4JHJ2nqEckLlBNNTXE8xCpMpo7Fzmpyi9fN8nJs+sjA9e7iavPMFWmf50y+X737eNMKJzlvvLr38+tK3r7Qvnm7/65udT96999KFpdeu/eft8+2rH9UHPnkXf1DSvnRn6c0Xl+982r7y9uKN6+3Pvu2c/W7xxoX2q+dRvnjnLh7Ab3Wunmi/erH9yhk81j5TrdSSM2/VZ258u3jr1vKtPyx/dxOXnd+dWrz18p9P/Lq+8vRcjgtNm/7L85OCKiccxQsvX/yi/e7bf/zm3tUL7c9f61z+7N4Lv21/eHryV7/A78zGxwcbQxEqJpidonZKNY0xezT4w0+gNSabq+cOH5r16clDfqHMzs00zezQzrUf/ykHPNJcVm960qfepai9cPblztVbvZLagfv+sXZIOjrnu83LOBo8/3Jht1/wtfufmvRHF2b3x3R4/+zc9FOTU09NPvpo69Bs9Id+fqS+xYr30/HcvrVw8OhMaPH9wT/z6NNHDjw1uWuNhfnp47kxga+zjzChVXN/en7/kaPzB/fHg9OH0lPVJZ6aPHLIH9s/4+eeqdfVR8v0oZm/8fO553hKs26LrHr2NBoQhUIq63A1/5PDqRkL0/N/l6vPNs6Gi9mZPONTXrl8EqYfr5bxXbUzDvk6Bgytjt29OuoPNCbNSh9gwC1/dr1anPHP5LlurzUfH5+dOeIPH+uWHPYz+fHq0asu3PNB3D0yHR+fPXQIHoV+mV/pijkhUV98Qjc9wjRtGqsXn+jG+CQ3jU+6lWRhiVlBtHGFSEUZsTJxkmXknHmtfTb9zmGKPoJBvM6S2GhJDbHEPfeqaEtM0JlIKSNxhVuCwRFUyRL9HPqWBKWPyA2WBmLusDoZBwczhREn8EMml4hXoZDCC2NaRU216FvSsGS3smSG1UnbJJhyhHsJN8dnEri1pOhgirGBqbLaeg7dxLdovGFVUtQEbmIk1IuE8RTQeCwHkrjkxvIiWE6rhjQM2dH+MKyXHBVFZMWJyzYQyThakXFNtCpCyBRhz3cN/aqO1jm0tGhaD46Iz4+IrZpyc6DULWto4UYUQrXWMIzK2UITUVmEpLSjlvUM1yFex/zjgKK52UO92Pf44YVnmzG8yb3/e3QWQ7MO1s3v/91RP3/waP/uHgSTlSFeL9dGV8nXRdfmcl04lT087Mbb5tL0o+tcPtRE114Ax3VGpEKIXQ35An9waz7OzqHQ1k9zOR/+p7nphV4EmT84O7ewG1i4cok79RuBxmrl9SqkdcF+fvboXFy5XV+mGwnvXFr6w++b2wt+bq7B8n95vnkBKypatG+cXLxxZ+nszT9+s3Tn9cXbn3Xe/xSPI5gy55rvv9n+/DYQ7I/ftD+42P7um+amUI5b1ti/+dritydw89w7zc1frFpCc9awtws8oP//ZHN74eh8E2nnj4bH15ASOBW19Z3Oftg5eQqP1oL6Eu3LV1HWLWBNwenf3Pv9x021joZ90wuHaqvWaPry68tfvdU+83H7ypX2rX9bvvPJ4o3L+L0Ff2DToLtrs+rvGqjzriF4vqv/YkePpM0R3UwpMyVkfWQ+z9XeQcvvmnzWz03nhWM/Ozj7XNMSz06nPPu3CP6zz438kua5v5+eX2i6cWx+N4xvmCnJpqjcSL761ABRU3dBlDvOlVOAv5l6OblLA1I13GDXaFhb/uxS+8x/gAc2+LYOjUeOX9q9/7MFvPrMfOPTine9YeZIfeF6yUT3cj8i+0oRZytFQvWKlF0pAuGurXFkdi7VAca2HDNNa69XBAMR1u4/dvTw8YN46xnfjXaqRUWLmZZSrSC9FxhpqgTHNZfCx1Q8oq1Pkhee9j/L9+/Z94Tasy/SPfsO0F4P/wysqBnmaH8lalhhTjotqWZ4pJZqUXkmQjYzCNi0/7brxEWtTef6+yvK4rmDCB9d35lsRnElYf84WMWBWL4GRDR1LWpWamcpU8lJTZISisgYLQlJBkKzBX4pEbwrk9tQIRu8VBPqCDWN+8spxNphXsqkAYE9Mj0/WxlcDZSNx2rpmNZm1WPR7lJUh17jsX8+cW7Qaf984uV7/3a5c+WtrjKbaN99Z+ncJ+1Tf2if+qT92e3O7dc6Nz5GiOpc/nzxztUuc+tS4x5pk2KVtLnxWcea5tWt7JgsSRuSNfVECkClc0ITy7KQcKvkMl3lbNw+4vTYlG2dIUGF4qkYUlQGZQNLI1ZHRVj0HmwOod76VUOCP+Lc9zPki7cpR0lMhXzJBSc2BwcCZ6zlUqZsVrkhfnWASA2MPj3EUuQqc8VAC0sGzdDCExiPuBTeaGXxHnzVkoUlocZmUussSbBqzWOGnrW81kmQINGMGuMSxdYYtkrZEGMeAbteZ4mNIIfrLNFiowILJM6CXsugHYabgtgK2RjoThf9qj+AVQ+QtFE0dH3rxRykVXADn6rnGQnPo5FwOB2GlFDRuLUkbRtxnd13qvVDwwQfzd62YF1j0ZNNcGZjXzG+AWfWdRgrissoS4xaBZd4YiI7xGDOSg6e9nDm2N7dT6i9T//k2EacYdIiNMK8lFxD6WwOJwO5qnERZcDxNqoD4CVrUdoywphoMifCW0qkYYEEb+DxMUkVgig2uR0gSjfpBN5DpxSb4nwjovyQWRbDN8Moo6wRag1Gce003HMsjGp/+mbn3fdF5+oZ0Xn9g4nl9/6w/PXbfzpxtX331NLVl+vPM1/gZ/u31/904q2VVrl/WLWu47KSNsaqWRkHhHANrBJob8OlRqBCLGEjsWrLREbPEA/JRgv6qmw2MKQ8hKthUP4iFu1UsFpvC6uGuWLK3ARnE/FWI657B+D1qBGqE6KhFszPjMSqUTRqnSWlnCgGzYb3r3E9SxJUUCRQJ5UXVFKfR2LVlrmZniWWea6vT6ywaLyYEnEcWOURJgw1TufkRmLVlomMniUnfAqQCBjIDk5BswClkJ5oRqM2AGG7JjezGVYNoKIYYil650IBQfLBVEveEytRRdjhivLKksT/OKzivIdVov+Y6j1mOD3SK+s/Ry09ImZ6xWJtsZ7ZAgHFj4KAG8cPowNKq+sGGEEc1DKIKHiiwfnMXICbO+Ei4E9Dd0W1goBsz/Fnju/d/diA0jIgbvXFpYbgsrbKLBQ1KRCmEKalGxMTn13A7b891CQcaqeOi5EDDr8h1ALogfj46SEcowuJcJ0CHJ5mEky2RHu8OVeByhR3ipHMTFA3xcSUfLAYqTfFSG24M2sx0oJzm/F03PKHv1k+++XS2TMrUm6i88W/d964tnjr1kp+opkY6rx5uX3+Mgrbd0/uFCLVkH5LiVKgiCdZBgFJwizxXkIoQKgymmMqlm9LzskhhizTMlmQKKdMleXZkxCcI3WyJggbM498FERuhcWrnhidzcyjHswB9K2mMBQj8cZ5F43kkrKREDng88PaTrDIiodjemEhSIy0JHAIR+0dZSmXLCMbCZFb5adXG09k7rwKJMc6o8Ul5Fyp4ywIliRoQJZ0JEQOtN6wcayzFUEqRzyFOdQJBAOsHdhfwC6AxMaZkRA5tiWjvAZCymoErZcYusgxSXIBCHKRWeL6fy9EDgE9+aOA3sCIcJuA3krHylZgUcJRaLZFBC9KLMyCRArhs2Fc2B7o7X16j9h7/OcDss9oapo0ooLGB4OvoKdZN9+oqZX3XQiO57IcesLpEmnQxLk642Z4wSceCI85ey0Q3+4byMkp9UBBjnE1FOUs34Bylo2Fcp0rb3X9rFmucHnpd+eXzt5c/u7SxMTyq+fbn77Tvn1z6dWv2q990bl+vnPuxPLJO+1//XDpzOn2K5c2gzum3Qre1VBK2fcAPPQhEEDCGz2J4P9EZnB0C0ZOuHNKGwUVR926AMf5FkF7mLcUk1LWqabCdCRSZeiaHBnJmoUkkix8TabUAYiU3AKIhlmyNZcvJCNBOEqkU5a4WEGcCe8Nk8b6uHbedDvEYVNIqmNBJKGzZyRxjADUTldkl8S6JLMr2kvGRhGHAUNiGE5Q7ZgHcUiVpoA01/SsE4RTY1zyNIi1iwTG0NbDWtEXBGVOaz7boUbFGRIwqAn3SYG2h5TzaG291Tz3qmcoEzRjCY3F0V+BVziH4uWJMxVFLoHH7WnrTckQLElePRCcQesErkWFJZbVdQ+CQ9ELY+Hz29PWw/zBKQexIxIRlpaqrVnV84lU9R5dVpFbO5I4jD2C4d+5lEJJDgZ18jDnBWNQHtZkYKgwLvzvJQ73RVurH4VmjDGL2Y8LukWNsJyxqGyWTuais87OFkQlmlihcT3N+OfB7DJXTNRmsdRpp63GA6zpkFpfraSicjOiwVnt3S6S7URab5lctDWJQFUrCs808zX9XKOFt4ZYDGsCP9RWppyYEjtOP9vKOmr6eWDa/YdkHW7z9DNwS/A1k/rcCJCtsUkHPA3ly6fuohyMovPGRWjrFeqxKrRvnGxfeGHx1vn2K29UOvI9hfZW6NLvRfBDoZ2MRCkgs/RCAS8hUB3DkHSC22jUjnLRfXfRJkK3Myi4CJLKvCPWeAM5TFnINpmS2Ci83DK73jPEBHMeUEYQ6xGH6yfntSQaQpiJlIOLdGe56H6VnA42C08yr0yqhExgmJLomQ9UJF2U39686dA6gfAG0HyiSqpCG81oS4BhZ6zUBTBS9M5y0T1LLidfLACSpWSJFHUuGJ5PfAxMi8B10Gl7QntY64WEoJYE6AXPQGatwHi59URJyb2Loc6qP8TLHeGl/gvORduKl0q0tBRRFa90pHDaFCUDUwtSAeZCTFz28XJ3fG7v7n8YwEvHBa+tohzlSuuqTlHkal0Y5DDbPBd9v9Byq5kXzhp2KMEOEwuOCZKKQayQVkB1FUFyVpojBOcQ1E7RkrNGo6spZR6sRnebwqXBGHJr4dJWXSHHgsulb8903n6hl4bu6vK+/8HzVjLRv75Wf++1a0tXry1/fmWnyWi9ad/ZVtbRakkjYVoiJiYwe+tdIVkpH4GPXq6N82NoSjPEUOQyopEDCbkG3wjUcjVCUpizzGQVyshk9IA3DquRZUoj/gL1ZY29IDHE62wIj0onMNhg1xr6HhjZt5QkGERhmnAAPKm5e+J9MUTmGJPgRQZHR2LkVmnvviUVPfiKYyTKOreJS+IMmExMKktqc0mBbQ8jh3WTAaegddW+c5B7kjt8opIRjVaSEuSjqJ1pyr4lKjJPAgxG+izhEC4QSONCFLeQ/d77TOVDjNwRRpq/CIzcNHXddYO6aMmkQhEETEbYUYI6rjV+JCMpl9mvasrjUe3d/ZjciJGI0Hi8akpuqDSCN5rSQb7V+hquQSN/4BnbUYsRm7rKFgPPda2cRYL31g0dpiZCPUU0jJRYDZ2iTADN3sk62S5QygkmpySA8oHKSq5oDxstl1yvzV876wyzY2Hjn05c7Zy51P7N+X4Wu7vLrq5b+vZ6+/Tv8QBE49K5T+qq26v/vnjrNG7d55nafn9R4YxMABBN68LbDP1TVzABK60XQnFhpdkROPYMqQgstEqRSJOqUVcSm60hKjjQRxtDkHIni5lWDSkRaILOAi+VdftXXQIULYH0YplZX3LYZsJVDvP1okuhLBHhqqwrWhBIr6rFoYB8kRCrYnvgOKzxoi4iaIev5rKm4r0koQC3qNPMOKWiCqMF5KiFt+tbLyG+JOkJ/gKHKRQ6XzFOQCu0SV7VKYHtCchh/RQLc9F4RWizmEl5iGJuPCxlHqAnMA4fJlx3Bo6c/zgLegckJNsMHmWd1pWuBWzkXKu6FCFBWWmpbVCiMKs8Fcr3Z3Z/uu8AJOQevhEe69I328zjKsclPNQ0zYLfrd2p8ElT/ePlXJtVW92ciWLa+QxmS1mxdRGJJdYEOL+P1gA0HS07zLkKwmiTc7VTij1QcJR2BRzrTBAXdBUcRc0JcDGecPzgo86Zu/dOnF5+7/rSy79uv/f28oe/Xrz9+tLJ650LH07UNOyps+2L10Bn8Kfuyt8hLg7rKuEVi6zmVEGugIt1HYnPgiASQ4445o3Q20qsmiGGIK9o1oDdAE4In3AcAdf5Co42MK1QYreFi8NqRIWwiN+FlGYbbLFAK6kYMd5XbLaZWrU90Ti0StrgP3i4DnUhjtOJeNSERMOF55m5LOz2JiL1EEvBJW8itXXzRhXCrEDKaU4yVGsylGqZR09Ejk4irLFkknUhJWjsZOqm8uyJl4BJprKFnLNgTmV7G1LUsH7yoYhcpx9zldyi8Lp9XRCOxuQx11We/CEu7myRr/gLWea7caPLGkfgLRU8dIUvjAVTUtIhg/0pBGBtDRMhr+Ai/+nuJ+Tep/9hEBeltU51cREhhTf7KVHodJNw5dIJselc5H3UjVvGDFE1sjStIHJCZEV08hQMN9atXxGuDyKfJZdJc293DI2iQqPkD3gRFLe6D40GQV6thUYNfx8PGtei3sTE4q0v29dfXbzx2/bVW4t331i++E3Nsn50sv3pf9z73d37vbS331G2BQajswNuQMrHusASgZD6Ou0YsjPUpsC3t7R3Y8TtGfIqyKi5JoiFFRijIMEi1IcYEOONKCblHQFjv0ZZslBXwHJRQYQqRxzTUFg+isQQy23eJjAOsxRp4EHnQKisCWKJ+B4UVcQmtBxgzHNuRgLjmMPJ4g/zQVBJioxVXAVUxzEGbS9d4MbEUOwOZhzXWgqibvOuCQSN1oMp4g0PJBlbMs0pqcy3l00d5hChsMJpUMS7CF6WUobchib2CI3KG2ZsTA+B8X8EMG6yRmcNVjBZVwCHoHRdjACqJ1QwCD1KOFdHUh8Y9z0h9ux+bBAYrVasthezgtZUXq1aLbR1gbCmgtXzQB7wFpiNCRlU01Y6KAtzUFCWFINYKJXnINPekKI9ShgzIu88odocPCDtlHiwM49S9RKqYCdynWZslmmPtzZn8cb1zuWX7p26cO/a/7/3xtftT2/Wowtun5iYqKnWN79a/vrzmlu99kH71QuLN77tnH+hrsk59zGe3SZIbpnb6nWaCTqxgsjrZUGoCkwSV/ADIdkohYCZndsWSG5M3/YMFQxlmwxiouAMtIlqAmOUCK6UltYozuK2QHJjBrJnCFbqpKmHGzKF4AtAsVWwVjAuqBPupZEgObYlJ5IDngiibTPRWI/vygGCOHphldUi8tFTjgO9xIdYitzHZLIjui70lBbQ4oTBZXGOZinqQuvtZVWHWeKGQ/OC2EZmAce5aOK1jCTXtUayvgUfPeW45TRqz1KATMXXh5pdqidCQIVDR0bCS/ExBmZitA9BckcgKeVfxn4ZJjbLqnaPSWAtLUQQPiiWlU3wNemVC6HELJVWmfWyqnzP8cfU3uODC3MQnFVzTILjFsPB1OUtKNPNSViATcrkD5pU3ZJUNyt2lW6VUkLyQRMRWV2aIzIJiWUiSoJSFrGERvjuTDk222cAkOwBb5/pJ1URz6VdC5BKqmZ3zTj7QiEOP3uxHpbwypeLN851rp6AVuzWGMA40f7gDm4v3rjQuXy9m39tn73UOf+SWrx192GI+O8dIgYnXnojR7qWUfXgFA5I4ozWTeEmcs0tFZ4bL2MvwQQO/cwv9zz98+cG1yVY0Wygs1xwuCNr1iVY2fQmN9Rp84OudR8Nv1ALrJ6bUFeAycwg8RmJtOYs6qkTtqamPYRjDMbryHa4eg/9ypqjVugDXpQAjtcLEXhCOrYmRKBICjfevMuX37XvfLzSJTtcq66H9IIKNKo6a60S50RqF0iQlhHGGAhQCXV787amVNQQQ7I47qmvYZtLEKECHm5kJjw4cEjBM6Mjz00ZTbbWGErCiWxlItnXfVC8slQRaorKZWnAITkffcbXVlmW1barR6DVZeoxsjr9wOqZtjYTwxyry2at3NFa9TWWXAaF5MISF/yKdPHKU2LRpBDI6CjmR5LirWZD+5Z4kkwZ6wnPDpKC1TNtRSk1kSRSNlnqMJoUj12negpaVPC8FNA70iRDXM7Q0J4Zn5m2+OshKd7Z3i714+zuGmMTedcRaEvZmjkqRaho66FGLmaheeA0F0RXKYTwPVK8d98///Knu+PASjxpEVJrVwmGXqv4V/vPWsaaeRYqMBjkg8W8jdlS1fi8aQnKtdBJEgQOxCZdT8bgnhF4Hg/KAJ553jEtVhOMTXE2Rd0DpcX9hXgWzart2gkVRZWT4y1SX7z5cvfz0tkzvS3k7VdvtG//rnPy1OJ373fefb997uP2uStdUrzTXNFG/dLrKOmZaI76UN2lIIyDl9RDOWwRCLYmyBxGweLoRWRrDKliQ5Ky1L26YEG+7ndKFpFdCCmsxChQI3NFY7ueASBpDa+z2oSVs1KFNMSYlHTKKkYx+qyUsdsOA66u8tMA4Hrah3YM2s9KUory2ietNRt9nNjYdUrOR+tMAXkJtfEkr2v7IxFcJBcls8qG7eWKNk6w9buJWvh1ZiR1l9HSQgJVEVVkOZpUt96H7eWKhjkEy17XiVVSmokvUElAPahZphGtiFjJzcMJlf+esDhwpObgJq6+I4hWMNyq6DlNdTWLchg7vuaKfIAHJOZWheBPjv1094HBBeqIuqL2nNNOsXqw+a5appt/GkUwY5jZ9HSVHwwUNxJBsbJbLSD8JJBMBFcPyplTJKEESWLioh5YFbIOOxaC3VUGeooNnOL8g4Ki6OeKKBSBWpsrEvXM4fFyRe1X3l9679IKHNZToG9+1X71Yv/R9ukL9V+befFa+9xH7VMfdc9fud+Csddb1FpXGGS78AjxUsi6EkrnejJ00PWwzexHrk3fUsf1DBUmk+U1KR993TVbZ5ZVicRECJS6VN14NQoZt5rC7huytG5n8ppYVw3VI1V8RN0wQKgzQjqE++2dIjbM06lOEco3k8i4qosaIONoPVLFBSkThwQvo08RGz1BubbxCiARPJoY4XydRalr8AInxuYgXQxUstGniI3dTcY46XM9FA3SET/q8glX6iknqohQSuhvOf5eG7fWWOJQCCyLmqWoh3fTWA84YeBkxSiuSsmCPUTGHW5u1j/O9uaB6LOpYOytOeEKo6WEmpvSgkedqQoS8OhsodSX/hq8vU9Hvvd4HEyRCquaf+fDWs2cMM3WLZQZXevr8PVs061b20PGX2ws+C/KaTU6");
//        DataHandle.dataHandle(sb.toString());
    }
}
